<?php

namespace App\Service\Article;

use App\Error\Article\ArticleCategoryError;
use App\Error\BaseError;
use App\Error\KfAdmin\CategoryError;
use App\Error\KfMerchant\ArticleError;
use App\Events\Article\OperateEvent;
use App\Exceptions\KfHttpResponseException;
use App\Http\Middleware\OpenShop\FeishuWebAuth;
use App\Http\Middleware\OpenShop\MerchantAppAuth;
use App\Http\Resources\Article\ApiArticleListResource;
use App\Http\Resources\Article\ArticleCategoryDetailResource;
use App\Http\Resources\Article\ArticleCategoryListResource;
use App\Http\Resources\Article\ArticleCategoryRelListResource;
use App\Http\Resources\Article\ArticleListResource;
use App\Http\Resources\Article\Category\UserOperateListResource;
use App\Http\Resources\Article\HotArticleCategoryListResource;
use App\Models\Article\ArticleCategoryMappingsModel;
use App\Models\Article\ArticleCategoryModel;
use App\Models\Article\ArticleModel;
use App\Models\Article\ArticleUserRelationModel;
use App\Models\Article\Category\ArticleCategoryOperateDailyStatisticsModel;
use App\Models\Article\Category\ArticleCategoryOperateHistoryModel;
use App\Models\Article\Category\ArticleCategoryOperateResultModel;
use App\Models\BaseModel;
use App\Service\BaseService;
use Darabonba\GatewaySpi\Models\InterceptorContext\request;
use Exception;
use Illuminate\Support\Facades\DB;

class ArticleCategoryService extends BaseService
{

    /**
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function list(object $params)
    {
        try {
            $paginate = ArticleCategoryModel::query()
                                            ->with(["createdByUidRel", "updatedByUidRel"])
                                            ->withCount([
                                                "articleCategoryMappingsRel as articleCount" => function ($query) {
                                                    $query->whereHas("articleRel", function ($query) {
                                                        $query->where("isDeleted", 0);
                                                    });
                                                }
                                            ])
                                            ->when(checkFieldLen($params, "name"), function ($query) use ($params) {
                                                $query->where("name", "like", "%{$params->name}%");
                                            })
                                            ->when(checkFieldLen($params, "description"),
                                                function ($query) use ($params) {
                                                    $query->where("description", "like", "%{$params->description}%");
                                                })
                                            ->when(checkFieldLen($params, "uid"), function ($query) use ($params) {
                                                $query->where("createdByUid", $params->uid);
                                            })
                                            ->when(
                                                attributeGet($params, "createStartTime", null),
                                                function ($query) use ($params) {
                                                    $query->where("createdAt", ">=",
                                                        strtotime($params->createStartTime));
                                                })
                                            ->when(
                                                attributeGet($params, "createEndTime", null),
                                                function ($query) use ($params) {
                                                    $query->where("createdAt", "<",
                                                        strtotime("+1 day", strtotime($params->createEndTime)));
                                                })
                                            ->when(
                                                checkFieldLen($params, "sortField"),
                                                function ($query) use ($params) {
                                                    $sort = attributeGet(
                                                        $params,
                                                        "sortOrder",
                                                        "descend"
                                                    ) == "descend" ? "desc" : "asc";
                                                    $query->orderBy($params->sortField, $sort);
                                                },
                                                function ($query) {
                                                    $query->orderBy("putTop", "desc")->orderBy("sort", "asc")->orderBy("id", "desc");
                                                }
                                            )
                                            ->paginate($params->pageSize, ['*'], 'pageNum', $params->pageNum);

            return [
                "list"     => ArticleCategoryListResource::collection($paginate->items()),
                "count"    => $paginate->total(),
                "pageNum"  => $params->pageNum,
                "pageSize" => $params->pageSize
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function add(object $params)
    {
        try {

            $category = ArticleCategoryModel::query()->insertGetId(array_merge((array)$params, [
                "createdByUid" => request()->user()->id,
                "updatedByUid" => request()->user()->id,
                "createdAt"    => time(),
                "updatedAt"    => time(),
                "type"         => ArticleCategoryModel::TYPE_SUBJECT
            ]));

            //操作记录添加
            ArticleCategoryOperateHistoryModel::query()->insertGetId([
                "targetId"     => $category,
                "operateType"  => ArticleCategoryOperateResultModel::OPERATE_TYPE_CATEGORY,
                "status"       => ArticleCategoryOperateResultModel::STATUS_SUCCESS,
                "createdAt"    => time(),
                "updatedAt"    => time(),
                "createdByUid" => request()->user()->id,
                "updatedByUid" => request()->user()->id
            ]);

            return [
                "categoryId" => $category
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }


    /**
     * @param object $params
     * @throws Exception
     */
    public static function update(object $params)
    {
        try {
            ArticleCategoryModel::query()->where('id', $params->id)->update(array_merge((array)$params, [
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id,
            ]));
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @throws Exception
     */
    public static function sort(object $params)
    {
        try {
            ArticleCategoryModel::query()->where('id', $params->id)->update(array_merge((array)$params, [
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id,
            ]));
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @throws Exception
     */
    public static function del(object $params)
    {
        try {
            ArticleCategoryModel::query()->where('id', $params->id)->update([
                "updatedAt"    => time(),
                "updatedByUid" => request()->user()->id,
                "isDeleted"    => BaseModel::DELETE_YES
            ]);

            //操作记录添加
            ArticleCategoryOperateHistoryModel::query()->insert([
                "targetId"     => $params->id,
                "operateType"  => ArticleCategoryOperateResultModel::OPERATE_TYPE_CATEGORY,
                "status"       => ArticleCategoryOperateResultModel::STATUS_CANCEL,
                "createdAt"    => time(),
                "updatedAt"    => time(),
                "createdByUid" => request()->user()->id,
                "updatedByUid" => request()->user()->id
            ]);
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function detail(object $params)
    {
        try {
            $detail = ArticleCategoryModel::query()->where('id', $params->id)->first();
            return [
                "detail" => ArticleCategoryDetailResource::collection([$detail])->getIterator()->current()
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function articleList(object $params)
    {
        try {
            $articleList = ArticleCategoryMappingsModel::query()
                                                       ->with("articleRel")
                                                       ->whereHas("articleRel", function ($query) {
                                                           $query->where("isDeleted", 0);
                                                       })
//                                                       ->when(
//                                                           checkFieldLen($params, "title"),
//                                                           function ($query) use ($params) {
//                                                               $query->whereIn("articleId",
//                                                                   function ($query) use ($params) {
//                                                                       $query->select("id")->from(
//                                                                           (new ArticleModel())->getTable()
//                                                                       )->where("title", "like",
//                                                                           "%{$params->title}%");
//                                                                   });
//                                                           })
                                                       ->where("categoryId", $params->id)
                                                       ->orderBy("sort")
                                                       ->get();

            return [
                "category" => self::detail($params)["detail"],
                "article"  => [
                    "list" => ArticleCategoryRelListResource::collection($articleList),
                ]
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param int $categoryId
     * @param string $articleTile
     * @return array
     */
    public static function getCategoryArticleGroupStatistics(int $categoryId, string $articleTile = ""): array
    {
        $groupStatistics = ArticleModel::query()
                                       ->when(
                                           $articleTile,
                                           function ($query) use ($articleTile) {
                                               $query->where("title", "like", "%{$articleTile}%");
                                           })
                                       ->whereIn(
                                           "id",
                                           function ($query) use ($categoryId) {
                                               $query->select("articleId")->from(
                                                   (new ArticleCategoryMappingsModel())->getTable()
                                               )->where("categoryId", $categoryId);
                                           })->select([
                DB::raw("count(*) as total"),
                DB::raw("sum(supportNum) as supportNumTotal"),
                DB::raw("sum(collectNum) as collectNumTotal"),
                DB::raw("sum(forwardNum) as forwardNumTotal"),
                DB::raw("sum(readNum) as readNumTotal"),
                DB::raw("sum(showNum) as showNumTotal"),
            ])->first();

        return [
            "total"           => attributeGet($groupStatistics, "total", 0),
            "supportNumTotal" => attributeGet($groupStatistics, "supportNumTotal", 0),
            "collectNumTotal" => attributeGet($groupStatistics, "collectNumTotal", 0),
            "forwardNumTotal" => attributeGet($groupStatistics, "forwardNumTotal", 0),
            "readNumTotal"    => attributeGet($groupStatistics, "readNumTotal", 0),
            "showNumTotal"    => attributeGet($groupStatistics, "showNumTotal", 0)
        ];
    }

    /**
     * 专题添加文章
     *
     * @param object $params
     * @throws Exception
     */
    public static function articleAdd(object $params)
    {
        try {
            $increaseSort = count($params->articleIds);
            //todo  已存在专题的文章排序统一增加 + 当前添加文章数量
            ArticleCategoryMappingsModel::query()
                                        ->where("categoryId", $params->id)
                                        ->update(["sort" => DB::raw("sort + {$increaseSort}")]);

            $exists = ArticleCategoryMappingsModel::query()
                                                  ->withoutGlobalScope("isDel")
                                                  ->where("categoryId", $params->id)
                                                  ->whereIn("articleId", $params->articleIds)
                                                  ->get();

            if ($exists) {
                $exists->each(
                    function (ArticleCategoryMappingsModel $articleCategoryMappingsModel) use (&$increaseSort) {
                        $articleCategoryMappingsModel->sort         = $increaseSort;
                        $articleCategoryMappingsModel->updatedByUid = request()->user()->id;
                        $articleCategoryMappingsModel->updatedAt    = time();
                        $articleCategoryMappingsModel->isDeleted    = 0;
                        $articleCategoryMappingsModel->save();
                        $increaseSort--;
                    });
            }

            $insertData = collect(array_diff($params->articleIds, $exists->pluck("articleId")->toArray()))
                ->map(function ($articleId) use ($params, &$increaseSort) {
                    $return = [
                        "categoryId"   => $params->id,
                        "articleId"    => $articleId,
                        "createdAt"    => time(),
                        "updatedAt"    => time(),
                        "createdByUid" => request()->user()->id,
                        "updatedByUid" => request()->user()->id,
                        "sort"         => $increaseSort
                    ];
                    $increaseSort--;
                    return $return;
                })->values()->toArray();

            if ($insertData) {
                ArticleCategoryMappingsModel::query()->insert($insertData);
            }
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 专题删除文章
     *
     * @param object $params
     * @throws Exception
     */
    public static function articleDel(object $params)
    {
        try {
            ArticleCategoryMappingsModel::query()
                                        ->where("categoryId", $params->id)
                                        ->whereIn("articleId", $params->articleIds)
                                        ->update([
                                            "updatedAt"    => time(),
                                            "updatedByUid" => request()->user()->id,
                                            "isDeleted"    => BaseModel::DELETE_YES
                                        ]);

        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 专题文章排序
     *
     * @param object $params
     * @throws Exception
     */
    public static function articleSort(object $params)
    {
        try {
            $categoryArticles = ArticleCategoryMappingsModel::query()
                                                            ->whereHas("articleRel", function ($query) {
                                                                $query->where("isDeleted", 0);
                                                            })
                                                            ->where("categoryId", $params->id)
                                                            ->get();

            if ($categoryArticles->count() != count($params->sort)) {
                throw new KfHttpResponseException(CategoryError::CATEGORY_ARTICLE_COUNT_NOT_EQ);
            }

            $sortIndexById = array_column($params->sort, "sort", "id");
            $categoryArticles->each(function (ArticleCategoryMappingsModel $articleCategoryMappingsModel)
            use ($sortIndexById) {
                $articleCategoryMappingsModel->sort         = $sortIndexById[$articleCategoryMappingsModel->articleId];
                $articleCategoryMappingsModel->updatedByUid = request()->user()->id;
                $articleCategoryMappingsModel->updatedAt    = time();
                $articleCategoryMappingsModel->save();
            });

        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @throws Exception
     */
    public static function operate(object $params)
    {
        try {
            //操作结果添加[点赞 ｜ 收藏]
            if (in_array($params->operateType, ArticleCategoryOperateResultModel::SAVE_RESULT_TYPE)) {
                $exists = ArticleCategoryOperateResultModel::query()
                                                           ->where("operateType", $params->operateType)
                                                           ->where("targetId", $params->targetId)
                                                           ->where("createdByUid", request()->user()->id)
                                                           ->where("status", $params->status)
                                                           ->first();

                if ($exists) {
                    throw new KfHttpResponseException(ArticleError::CATEGORY_OPERATE_REPEAT);
                }

                ArticleCategoryOperateResultModel::query()->updateOrCreate(
                    [
                        "operateType"  => $params->operateType,
                        "targetId"     => $params->targetId,
                        "createdByUid" => request()->user()->id,
                    ],
                    array_merge((array)$params, [
                        "updatedAt"    => time(),
                        "updatedByUid" => request()->user()->id
                    ])
                );
            }

            //异步操作记录
            event(new OperateEvent(
                request()->user()->id,
                $params->targetId,
                $params->operateType,
                $params->status,
                time()
            ));

        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 操作列表
     *
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function operateList(object $params)
    {
        try {
            $paginate = ArticleCategoryOperateResultModel::query()
                                                         ->where("status", ArticleUserRelationModel::STATUS_SUCCESS)
                                                         ->where("operateType", $params->type)
                                                         ->where("createdByUid", request()->user()->id)
                                                         ->with(["categoryRel"])
                                                         ->whereHas("categoryRel", function ($query) use ($params) {
                                                             if (checkFieldLen($params, "name")) {
                                                                 $query->where("name", "like", "%{$params->name}%");
                                                             }
                                                         })
                                                         ->orderBy("id", "desc")
                                                         ->paginate($params->pageSize, ['*'], 'pageNum',
                                                             $params->pageNum);

            return [
                "list"     => UserOperateListResource::collection($paginate->items()),
                "count"    => $paginate->total(),
                "pageNum"  => $params->pageNum,
                "pageSize" => $params->pageSize
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function groupStatistics(object $params)
    {
        try {
            $categoryGroupStatistics = ArticleCategoryOperateDailyStatisticsModel::query()
                                                                                 ->when(
                                                                                     checkFieldLen($params,
                                                                                         "categoryId"),
                                                                                     function ($query) use ($params) {
                                                                                         $query->where("targetId",
                                                                                             $params->categoryId);
                                                                                     }, function ($query) {
                                                                                     $query->where("targetId", 0);
                                                                                 })
                                                                                 ->where("date", ">=",
                                                                                     $params->startTime)
                                                                                 ->where("date", "<=",
                                                                                     $params->endTime)
                                                                                 ->get();

            $daysCollect = [$params->startTime];
            $days        = (strtotime($params->endTime) - strtotime($params->startTime)) / (24 * 60 * 60);
            while ($days > 0) {
                $tempEndTime = end($daysCollect);
                array_push($daysCollect, date("Y-m-d", strtotime("+1 day", strtotime($tempEndTime))));
                $days--;
            }


            return [
                "list" => collect($daysCollect)->map(function ($date) use ($categoryGroupStatistics, $params) {
                    if ($date == date("Y-m-d", time())) {
                        return array_merge(["date" => $date],
                            self::getTodayStatistics(attributeGet($params, "categoryId", 0)));
                    } else {
                        return [
                            "date"        => $date,
                            "categoryNum" => attributeGet($categoryGroupStatistics->where("date", $date)
                                                                                  ->where("operateType",
                                                                                      ArticleCategoryOperateResultModel::OPERATE_TYPE_CATEGORY)
                                                                                  ->first(), "totalNum", 0),
                            "showNum"     => attributeGet($categoryGroupStatistics->where("date", $date)
                                                                                  ->where("operateType",
                                                                                      ArticleCategoryOperateResultModel::OPERATE_TYPE_SHOW)
                                                                                  ->first(), "netNum", 0),
                            "readNum"     => attributeGet($categoryGroupStatistics->where("date", $date)
                                                                                  ->where("operateType",
                                                                                      ArticleCategoryOperateResultModel::OPERATE_TYPE_READ)
                                                                                  ->first(), "netNum", 0),
                            "forwardNum"  => attributeGet($categoryGroupStatistics->where("date", $date)
                                                                                  ->where("operateType",
                                                                                      ArticleCategoryOperateResultModel::OPERATE_TYPE_FORWARD)
                                                                                  ->first(), "netNum", 0),
                            "supportNum"  => attributeGet($categoryGroupStatistics->where("date", $date)
                                                                                  ->where("operateType",
                                                                                      ArticleCategoryOperateResultModel::OPERATE_TYPE_SUPPORT)
                                                                                  ->first(), "netNum", 0),
                            "collectNum"  => attributeGet($categoryGroupStatistics->where("date", $date)
                                                                                  ->where("operateType",
                                                                                      ArticleCategoryOperateResultModel::OPERATE_TYPE_COLLECT)
                                                                                  ->first(), "netNum", 0),
                        ];
                    }
                })->values()->toArray()
            ];
        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 获取当日统计数据
     *
     * @param int $targetId
     * @return array
     */
    public static function getTodayStatistics(int $targetId): array
    {
        //获取当日数据
        $categoryGroupStatisticsToday = ArticleCategoryOperateHistoryModel::query()
                                                                          ->when(
                                                                              $targetId,
                                                                              function ($query) use ($targetId) {
                                                                                  $query->where("targetId", $targetId);
                                                                              })
                                                                          ->where("updatedAt", ">=",
                                                                              strtotime(date("Y-m-d",
                                                                                      time()) . " 00:00"))
                                                                          ->where("updatedAt", "<=", time())
                                                                          ->groupBy(["operateType", "status"])
                                                                          ->select([
                                                                              DB::raw("count(*) as total"),
                                                                              "operateType",
                                                                              "status"
                                                                          ])->get();

        $getNumFunc = function (int $operateType) use ($categoryGroupStatisticsToday) {
            $successNum = attributeGet(
                $categoryGroupStatisticsToday->where("operateType", $operateType)
                                             ->where("status",
                                                 ArticleCategoryOperateResultModel::STATUS_SUCCESS)
                                             ->first(),
                "total",
                0
            );
            $cancelNum  = attributeGet(
                $categoryGroupStatisticsToday->where("operateType", $operateType)
                                             ->where("status", ArticleCategoryOperateResultModel::STATUS_CANCEL)
                                             ->first(),
                "total",
                0
            );
            return $successNum - $cancelNum;
        };

        return [
            "categoryNum" => $targetId > 0 ? 0 : ArticleCategoryModel::query()->count(),
            "showNum"     => $getNumFunc(ArticleCategoryOperateResultModel::OPERATE_TYPE_SHOW),
            "readNum"     => $getNumFunc(ArticleCategoryOperateResultModel::OPERATE_TYPE_READ),
            "forwardNum"  => $getNumFunc(ArticleCategoryOperateResultModel::OPERATE_TYPE_FORWARD),
            "supportNum"  => $getNumFunc(ArticleCategoryOperateResultModel::OPERATE_TYPE_SUPPORT),
            "collectNum"  => $getNumFunc(ArticleCategoryOperateResultModel::OPERATE_TYPE_COLLECT),
        ];
    }

    /**
     * 热门专题列表
     *
     * @param object $params
     * @return array
     */
    public static function hotList(object $params): array
    {
        $list = ArticleCategoryOperateDailyStatisticsModel::query()
                                                          ->with("articleCategoryRel")
                                                          ->whereHas("articleCategoryRel")
                                                          ->where("date", ">=", $params->startTime)
                                                          ->where("date", "<=", $params->endTime)
                                                          ->where("targetId", ">", 0)
                                                          ->where("operateType",
                                                              ArticleCategoryOperateResultModel::OPERATE_TYPE_SHOW)
                                                          ->groupBy("targetId")
                                                          ->select([DB::raw("sum(netNum) as showNum"), "targetId"])
                                                          ->orderByDesc("showNum")
                                                          ->limit(10)
                                                          ->get();

        return [
            "list" => HotArticleCategoryListResource::collection($list)
        ];
    }

    /**
     * @param object $params
     * @return array|void
     * @throws Exception
     */
    public static function apiDetail(object $params)
    {
        try {
            $action     = request()->route()->getAction();
            $middleware = attributeGet($action, "middleware", []);
            $firstPage  = [];

            if ($params->pageNum == 1) {
                $uid     = 0;
                $detail  = self::detail($params)["detail"];
                $collect = $support = false;
                //todo 商家端请求 判断是否点赞收藏
                if (in_array(MerchantAppAuth::class, $middleware)) {
                    $uid     = request()->user()->id;
                    $support = (bool)ArticleCategoryOperateResultModel::query()
                                                                      ->where("createdByUid", $uid)
                                                                      ->where("targetId", $params->id)
                                                                      ->where("operateType",
                                                                          ArticleCategoryOperateResultModel::OPERATE_TYPE_SUPPORT)
                                                                      ->where("status",
                                                                          ArticleCategoryOperateResultModel::STATUS_SUCCESS)
                                                                      ->first();
                    $collect = (bool)ArticleCategoryOperateResultModel::query()
                                                                      ->where("targetId", $params->id)
                                                                      ->where("createdByUid", $uid)
                                                                      ->where("operateType",
                                                                          ArticleCategoryOperateResultModel::OPERATE_TYPE_COLLECT)
                                                                      ->where("status",
                                                                          ArticleCategoryOperateResultModel::STATUS_SUCCESS)
                                                                      ->first();

                }

                $firstPage = array_merge($firstPage, [
                    "detail"  => $detail,
                    "collect" => $collect,
                    "support" => $support
                ]);
                //todo 异步操作记录 增加文章阅读数
                event(new OperateEvent(
                    $uid,
                    $params->id,
                    ArticleCategoryOperateResultModel::OPERATE_TYPE_READ,
                    ArticleCategoryOperateResultModel::STATUS_SUCCESS,
                    time()
                ));
            }

            //todo 获取文章信息
            $CategoryMappingsTableName = (new ArticleCategoryMappingsModel())->getTable();
            $paginate                  = ArticleCategoryMappingsModel::query()
                                                                     ->when(
                                                                         in_array(MerchantAppAuth::class, $middleware),
                                                                         function ($query) {
                                                                             $query->with(
                                                                                 [
                                                                                     "articleUserRelationRel" => function (
                                                                                         $query
                                                                                     ) {
                                                                                         $query->where("createdByUid",
                                                                                             request()->user()->id)
                                                                                               ->whereIn("type",
                                                                                                   [
                                                                                                       ArticleUserRelationModel::TYPE_LIKE,
                                                                                                       ArticleUserRelationModel::TYPE_COLLECT
                                                                                                   ])
                                                                                               ->where("status",
                                                                                                   ArticleUserRelationModel::STATUS_SUCCESS);
                                                                                     }
                                                                                 ]);
                                                                         })
                                                                     ->join(
                                                                         vsprintf("%s as %s", [
                                                                             (new ArticleModel())->getTable(),
                                                                             "article"
                                                                         ]),
                                                                         "$CategoryMappingsTableName.articleId",
                                                                         "article.id"
                                                                     )
                                                                     ->where("article.isDeleted", "=", 0)
                                                                     ->where("article.status", ArticleModel::STATUS_ON)
                                                                     ->whereIn("article.publishType",
                                                                         [
                                                                             ArticleModel::PUBLISH_TYPE_TIMING,
                                                                             ArticleModel::PUBLISH_TYPE_NOW
                                                                         ])
                                                                     ->where("article.effectiveTime", "<=", time())
                                                                     ->where(
                                                                         vsprintf("%s.%s", [
                                                                             $CategoryMappingsTableName,
                                                                             "isDeleted"
                                                                         ]),
                                                                         "=",
                                                                         0
                                                                     )
                                                                     ->where("categoryId", $params->id)
                                                                     ->orderBy("{$CategoryMappingsTableName}.sort")
                                                                     ->orderByDesc("{$CategoryMappingsTableName}.updatedAt")
                                                                     ->orderByDesc("{$CategoryMappingsTableName}.id")
                                                                     ->paginate(
                                                                         $params->pageSize,
                                                                         ["article.*", "articleId"],
                                                                         'pageNum',
                                                                         $params->pageNum
                                                                     );

            return array_merge($firstPage, [
                "article" => [
                    "list"     => ApiArticleListResource::collection($paginate->items()),
                    "count"    => $paginate->total(),
                    "pageNum"  => $params->pageNum,
                    "pageSize" => $params->pageSize
                ]
            ]);

        } catch (Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * 置顶
     *
     * @param object $params
     * @param int $uid
     */
    public static function putTop(object $params, int $uid)
    {
        if ($params->putTop == ArticleCategoryModel::PUT_TOP_YES) {
            $count = ArticleCategoryModel::query()
                                         ->where("id", "<>", $params->id)
                                         ->where("putTop", $params->putTop)
                                         ->count();
            if ($count >= 6) {
                throw new KfHttpResponseException(ArticleCategoryError::NO_MORE_THAN_THREE_TOPICS_CAN_BE_PLACED_AT_THE_TOP);
            }
        }

        ArticleCategoryModel::query()->where("id", $params->id)->update([
            "putTop"       => $params->putTop,
            "updatedAt"    => time(),
            "updatedByUid" => $uid
        ]);
    }
}
